﻿#include "Pri_Socket.h"

#define MIN_READ_BUFFER 64


Pri_Socket::Pri_Socket(int socket_id, unsigned int context_handle, int protocol, int socket_fd)
{
	m_context_handle = context_handle;
	m_protocol = protocol;
	m_socket_fd = socket_fd;
	m_read_size = 0;
	m_socket_id = socket_id;
	m_read_size = MIN_READ_BUFFER;
}

Pri_Socket::~Pri_Socket()
{
}

bool Pri_Socket::socket_direct_send(char *buf, int size)
{
	if (m_write_buffer_list.size()==0&&m_socket_sate_type==SocketStateType::SOCKET_TYPE_CONNECTED)
	{
		int sz = write(m_socket_fd, buf, size);
		if (sz==size)
		{
			return true;
		}
		else if(sz<0)
		{
			return false;
		}
	}
	return false;
}

int Pri_Socket::socket_send_buffer()
{
	std::unique_lock<std::mutex>{m_write_buffer_mutex};
	if (m_protocol ==SocketProtocol_Tcp)
	{
		for (WriteBuffer a : m_write_buffer_list)
		{
			ssize_t sz = write(m_socket_fd, a.buffer, a.size);
			if (sz < 0)
			{
				switch (errno) {
					case EINTR:
						continue;
				}
				//force_close(ss, s, l, result);
				return SOCKET_CLOSE;
			}
			a.release_buffer();
		}
		m_write_buffer_list.clear();
	}

	return -1;
}

int Pri_Socket::push_data_to_write_buffer(char * buffer, int size)
{
	std::unique_lock <std::mutex>ck{ m_write_buffer_mutex };
	m_write_buffer_list.push_back(WriteBuffer(buffer, size));
	return 0;
}

void Pri_Socket::set_socket_noblocking()
{
	int flag = fcntl(m_socket_fd, F_GETFL, 0);
	if (-1 == flag) {
		return;
	}

	fcntl(m_socket_fd, F_SETFL, flag | O_NONBLOCK);
}

void Pri_Socket::set_secket_keepalive()
{
	int keepalive = 1; 
	setsockopt(m_socket_fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepalive, sizeof(keepalive));
}

const char * Pri_Socket::get_socket_state_text()
{
	switch (m_socket_sate_type)
	{
		case SOCKET_TYPE_CONNECTED:
			return "SOCKET_TYPE_CONNECTED";
		case SOCKET_TYPE_HALFCLOSE:
			return "SOCKET_TYPE_HALFCLOSE";
		case SOCKET_TYPE_LISTEN:
			return "SOCKET_TYPE_LISTEN";
		default:
			return " 未知状态 ";
			break;
	}
}

void Pri_Socket::print_socket_infor()
{
	printf("Socket Infor：\n\
			socket_id :		%d \n\
			socket_state:	%s \n\
		",this->m_socket_id,this->get_socket_state_text());
}
